#include "cTools.h"

MyMessageboxA *MsgBox;
MySleep *pSleep;
MyGetModuleFileName *pGetModuleFileName;
MyCreateThread *pCreateThread;
MyLoadLibrary *pLoadLibrary;
MyVirtualProtect *pVirtualProtect;
MyGetModuleHandle *pGetModuleHandle;

extern cTools *pTools;

//-----------------------//
// cTools::MemPatch
//-----------------------//
VOID cTools::MemPatch(PUCHAR dest, CONST PUCHAR src, INT len)
{
	DWORD dwOld;
	pVirtualProtect(dest, len, PAGE_READWRITE, &dwOld);
	for(int i = 0; i < len; i++)
	{
		dest[i] = src[i];
	}
	pVirtualProtect(dest, len, dwOld, &dwOld);
	FlushInstructionCache(0, dest, len);
}
//-----------------------//
// cTools::MemPatch
//-----------------------//
VOID cTools::MemSet(PBYTE dest, INT val, INT len)
{
	DWORD dwOld;
	pVirtualProtect(dest, len, PAGE_READWRITE, &dwOld);
	for(int i = 0; i < len; i++)
	{
		dest[i] = val;
	}
	pVirtualProtect(dest, len, dwOld, &dwOld);
}
//-----------------------//
// cTools::DirectMemAlloc
//-----------------------//
VOID cTools::DirectMemAlloc(PUCHAR dest, INT len)
{
	DirectMemAllocMemPtr = new (dest) unsigned char[len];
}

//-----------------------//
// cTools::MemXorJmp
//-----------------------//
VOID cTools::MemXorJmp(DWORD xorcave, DWORD jumpto)// written by Hans211
{
	struct {
		BYTE    op1;               // mov eax, adr
		DWORD   adr;
		BYTE    op2;               // xor eax, mask
		DWORD   mask;
		BYTE    jmp;               // jmp eax
		BYTE    eax;
	} MASQ = { 0xb8,0,0x35,0x55,0xff,0xe0};

	MASQ.adr = jumpto^MASQ.mask;
	DWORD dwOld;
	pVirtualProtect((void*)xorcave, 12, PAGE_READWRITE, &dwOld);
	memset((BYTE*)xorcave, MASQ.op1, 1); //2 (const unsigned char *)
	*(DWORD*)(xorcave + 1) = MASQ.adr;
	memset((BYTE*)xorcave + 5, MASQ.op2, 1);
	memset((BYTE*)xorcave + 6, MASQ.mask, 1);
	memset((BYTE*)xorcave + 10, MASQ.jmp, 1);
	memset((BYTE*)xorcave + 11, MASQ.eax, 1);
	pVirtualProtect((void*)xorcave, 12, dwOld, &dwOld);
}

//-----------------------//
// cTools::MemHotPatch
//-----------------------//
DWORD cTools::MemHotPatch(DWORD adr, DWORD caveadr, bool dip_special, bool r) // written by Hans211, edited by N1ghtmare
{
	if(!dip_special){
		BYTE ndata[] = { 0xe9,0x00,0x00,0x00,0x00,0xeb, 0xf9};
		adr-=5;  // go back to where the nops should be
		*(DWORD*)(&ndata[1]) =  (caveadr - adr) - 5;	    	 // put the correct offset in the repl string
		MemPatch((UCHAR*)adr, ndata,7);

		return (adr+7);
	}
	else{
		if(!r){
			BYTE ndata[] = { 0xe9,0x00,0x00,0x00,0x00};
			BYTE dipdata[] = {0xeb, 0xc9};
			adr-=5;  // go back to where the nops should be
			*(DWORD*)(&ndata[1]) =  (caveadr - adr)-5;	    	 // put the correct offset in the repl string
			MemPatch((UCHAR*)adr, ndata, 5);
			long offset = 53;// xor ebx,ebx//0x28; //0x4FDD8863(xor edi, edi) - adr;
			adr += offset;
			MemPatch((UCHAR*)adr, dipdata, 2);

			return (adr+2);
		}
		else{
			BYTE ndata[] = { 0xe9,0x00,0x00,0x00,0x00};
			BYTE dipdata[] = {0xeb, 0xcb};
			adr-=5;  // go back to where the nops should be
			*(DWORD*)(&ndata[1]) =  (caveadr - adr)-5;	    	 // put the correct offset in the repl string
			MemPatch((UCHAR*)adr, ndata, 5);
			long offset = 51;// xor ebx,ebx//0x28; //0x4FDD8863(xor edi, edi) - adr;
			adr += offset;
			MemPatch((UCHAR*)adr, dipdata, 2);

			return (adr+2);
		}
	}
}

//-----------------------//
// cTools::FindDevice
//-----------------------//
DWORD** cTools::FindDevice(VOID) // written by Croner
{
    DWORD Base = (DWORD)pLoadLibrary("d3d9.dll");

    for(DWORD i = 0; i < 0x128000; i++ )
    {
      if ( (*(BYTE *)(Base+i+0x00))==0xC7
        && (*(BYTE *)(Base+i+0x01))==0x06
        && (*(BYTE *)(Base+i+0x06))==0x89
        && (*(BYTE *)(Base+i+0x07))==0x86
        && (*(BYTE *)(Base+i+0x0C))==0x89
        && (*(BYTE *)(Base+i+0x0D))==0x86 )
        return (unsigned long**)(Base + i + 2);
    }
    return NULL;
}  

//-----------------------//
// cTools::CallAPI
//-----------------------//
DWORD cTools::FindAPI(CONST PCHAR DLLName, CONST PCHAR FunctionName) // written by M4xCoding // szukanie api bez tablicy importow (nie wazne)
{
   unsigned char GetKernel32Shell[] = "\x31\xC9\x64\x8B\x71\x30\x8B\x76\x0C\x8B\x76\x1C\x8B\x46\x08\x8B\x7E\x20\x8B\x36"
                           "\x38\x4F\x18\x75\xF3\xC3";

   char*      LoadLib            = "LoadLibraryA";

   long KernelShellAddr = (long)GetKernel32Shell;
   unsigned long ListGPA = 0;
   unsigned long mzKernel = 0;
   unsigned long peKernel = 0;
   unsigned long anKernel = 0;
   unsigned long etKernel = 0;
   unsigned long ProcAddr = 0;
   char*        sTemp;
   _asm
   {

   call KernelShellAddr
   mov [mzKernel], eax

   mov esi, eax
   add esi, dword ptr [eax+0x3C]
   mov [peKernel], esi

   add esi, 0x78
   add eax, dword ptr [esi]
   mov [etKernel], eax

   mov ebx, [mzKernel]
   add ebx, dword ptr [eax+0x20]
   mov [anKernel], ebx

   mov edi, [anKernel]
   xor ecx, ecx

   LIST_GPA:
   mov ebx, [mzKernel]
   add ebx, dword ptr [edi]
   mov sTemp, ebx
   pushad
   }
   if (strcmp((const char*)sTemp, (const char*)"GetProcAddress") == 0)
   {
      _asm
      {
         popad
         jmp GOT_PROC1
      
      }
   }
   _asm
   {
   popad
   jmp ResPrc

   ResPrc:
   add edi, 4
   inc ecx
   jmp LIST_GPA

   GOT_PROC1:
   mov edi, ecx

   mov eax, [etKernel]
   mov ebx, [mzKernel]
   add eax, 0x24
   add ebx, dword ptr [eax]
   rol ecx, 1
   add ebx, ecx

   xor ecx, ecx
   movzx ecx, word ptr [ebx]
   rol ecx, 2
   mov eax, [etKernel]
   mov ebx, [mzKernel]
   add eax, 0x1C
   add ebx, dword ptr [eax]
   add ebx, ecx
   mov eax, dword ptr [ebx]
   add eax, [mzKernel]
   mov [ListGPA], eax
   
   push LoadLib
   push mzKernel
   Call ListGPA

   push DLLName
   Call eax

   push FunctionName
   push eax
   call ListGPA
   Mov ProcAddr, eax
}  
   return ProcAddr;
}

//-----------------------//
// cTools::add_log
//-----------------------//
VOID __cdecl  cTools::add_log(CONST PCHAR fmt, ...) // dodawanie logu w postaci pliku tekstowego
{
   va_list va_alist;
   char logbuf[256];
   FILE * fp;
   struct tm * current_tm;
   time_t current_time;

   time (&current_time);
   current_tm = localtime (&current_time);

   sprintf (logbuf, "[%02d:%02d:%02d] ", current_tm->tm_hour, current_tm->tm_min, current_tm->tm_sec);
   
   va_start (va_alist, fmt);
   _vsnprintf (logbuf+strlen(logbuf), sizeof(logbuf) - strlen(logbuf), fmt, va_alist);
   va_end (va_alist);
   strcpy(logfn,dllfn);
   logfn[strlen(logfn)-4]=0;	// strip .dll
	strcat(logfn,"_log.txt");
   if ( (fp = fopen ( logfn , "a")) != NULL )
   {
      fprintf ( fp, "%s\n", logbuf );
      fclose (fp);
   }
}
//-----------------------//
// cTools::bCompare
//-----------------------//
bool cTools::bCompare(PBYTE pData, PBYTE bMask, PCHAR szMask) //written by sb // funkcja do skanowania pamieci
{
	for(;*szMask;++szMask,++pData,++bMask)
		if(*szMask=='x' && *pData!=*bMask ) 
			return false;

	return (*szMask) == NULL;
}
//-----------------------//
// cTools::FindPattern
//-----------------------//
DWORD cTools::FindPattern(DWORD dwAddress,DWORD dwLen,PBYTE bMask,PCHAR szMask) //written by sb // funkcja do skanowania pamieci
{
	for(DWORD i=0; i < dwLen; i++)
		if( bCompare( (BYTE*)( dwAddress+i ), bMask, szMask) )
			return (DWORD)(dwAddress+i);

	return 0;
}
//-----------------------//
// cTools::XorStr
//-----------------------//
VOID cTools::XorStr(char* str, int key)
{
	int len = strlen(str);

	for(int i = 0; i < len; i++){
		str[i] ^= key;
	}
}
//-----------------------//
// cTools::GetFrameRate
//-----------------------//
char* WINAPI cTools::GetFrameRate()
{
	static float						 fFps            = NULL;
	static float                        fLastTickCount        = NULL;
	static float                        fCurrentTickCount;
	static char                        cFrameRate[50]        = {NULL};
	fCurrentTickCount = clock() * 0.001f;
	++fFps;
	if( (fCurrentTickCount - fLastTickCount) > 1.0f ){
		fLastTickCount = fCurrentTickCount;
		sprintf( cFrameRate, "%d", int( fFps ) );
		fFps = 0;
	}
	return cFrameRate;
}
//-----------------------//
// cTools::GetFrameRate
//-----------------------//
HRESULT cTools::GenerateTexture(IDirect3DDevice9 *pD3Ddev, IDirect3DTexture9 **ppD3Dtex, DWORD colour32)
{
	if( FAILED(pD3Ddev->CreateTexture(8, 8, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, ppD3Dtex, NULL)) )
		return E_FAIL;
 
	WORD colour16 = ( ( WORD ) ( ( colour32 >> 28 ) & 0xF ) << 12 )
	| (WORD)( ( ( colour32 >> 20 ) & 0xF ) << 8 )
	| (WORD)( ( ( colour32 >> 12 ) & 0xF ) << 4 )
	| (WORD)( ( ( colour32 >> 4 ) & 0xF ) << 0 );

	D3DLOCKED_RECT d3dlr; 
	(*ppD3Dtex)->LockRect(0, &d3dlr, 0, 0);
	WORD *pDst16 = (WORD*)d3dlr.pBits;
	for(int xy=0; xy < 8*8; xy++)
		*pDst16++ = colour16;
	(*ppD3Dtex)->UnlockRect(0);
	return S_OK;
}